#!/usr/bin/env python
# encoding: utf-8
# @author: Lin Han
# @contact: voldemort22@126.com
# @file: deprecated_app.py
# @time: 2021/3/23 15:33
# @desc:
import json
from fastapi import APIRouter, File, UploadFile, Request

from application.standard_clamp.crud import generate_standard_clamp_data, filter_standard_clamp_under_20, generate_standard_clamp_data_v3
from application.standard_clamp.queryModels import UploadStandardClampModel
from models.queryModels import MultipleConditionQueryStandardClamps, UpdateOneStandardClamp
from models.responseModels import ResponseDict, ResponseBool, ResponseStr
from utils.mongo_tools import retrieve_mongo_values, delete_mongo_value, update_mongo_value, create_one_mongo_value, retrieve_one_mongo_value, standard_clamp_number_generator
from utils.utils import create_folder, write_file, read_json
from views.configs import *
from views.crud import upload_to_aliyun_standard_clamp_model, is_part_in_database, send_to_message_queue, keyword_search_standard_clamp, separate_page

deprecated_standard_clamp_router = APIRouter(
    # prefix="/api/standardclamp",
    prefix="/api/standard_clamp",
    tags=["standard_clamp"],
)


@deprecated_standard_clamp_router.post("/v1/standard_clamps", response_model=ResponseDict)
async def multiple_condition_query_standard_clamps(request: Request, queryModel: MultipleConditionQueryStandardClamps):
    """
    列表查询多条标准夹具。输入参数所有字段均可为空。

    - :param queryModel:
    - :return:
    """
    model = {"data": {"result": []}}

    result = []
    # 先把redis中的符合历史夹具的key都拿出来
    standard_clamp_number_list = await request.app.state.redis.get("standard_clamp")
    standard_clamp_number_list = json.loads(standard_clamp_number_list)
    # 用上面的number列表去redis中查询所有历史夹具
    for i in standard_clamp_number_list:
        temp_item = await request.app.state.redis.get(i)
        if temp_item is None:
            # 去mongo中查询这个id的数据
            temp_result = retrieve_one_mongo_value(i, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
            # 如果mongo里能查到这条数据再把它更新到redis中
            if len(temp_result) > 0:
                temp_item = temp_result[0]
                # 把mongo中查到的数据set到redis数据库中
                await request.app.state.redis.set(temp_item["number"], json.dumps(temp_item))
            else:
                # 若是走到这一步那说明不但redis里没有，连mongo里面也没有这个number的数据了，就跳过append吧
                continue
        else:
            temp_item = json.loads(temp_item)
        result.append(temp_item)

    result = keyword_search_standard_clamp(queryModel, result)
    model["data"]["total"] = len(result)
    if len(result) > 0:
        if not queryModel.isTotal:
            model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
        else:
            model["data"]["result"] = result
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.get("/v1/standard_clamp_version", response_model=ResponseDict)
async def get_standard_clamp_version(request: Request):
    """
    获取 标准夹具 版本配置

    - :return:
    """
    model = {"data": {}}

    result = []
    # 先把redis中的符合历史夹具的key都拿出来
    standard_clamp_number_list = await request.app.state.redis.get("standard_clamp")
    standard_clamp_number_list = json.loads(standard_clamp_number_list)
    # 用上面的number列表去redis中查询所有历史夹具
    for i in standard_clamp_number_list:
        temp_item = await request.app.state.redis.get(i)
        if temp_item == None:
            # 去mongo中查询这个id的数据
            temp_result = retrieve_one_mongo_value(i, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
            # 如果mongo里能查到这条数据再把它更新到redis中
            if len(temp_result) > 0:
                temp_item = temp_result[0]
                # 把mongo中查到的数据set到redis数据库中
                await request.app.state.redis.set(temp_item["number"], json.dumps(temp_item))
            else:
                # 若是走到这一步那说明不但redis里没有，连mongo里面也没有这个number的数据了，就跳过append吧
                continue
        else:
            temp_item = json.loads(temp_item)
        result.append(temp_item)

    version_list = []
    for i in result:
        if "version" in i.keys():
            if i["version"] not in version_list:
                version_list.append(i["version"])
    model["data"]["version"] = version_list
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.delete("/v1/standard_clamp", response_model=ResponseBool)
async def delete_standard_clamp(number: str):
    """
    删除一条标准夹具数据。

    - :param number:
    - :return:
    """
    model = {}
    delete_mongo_value(
        number=number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_CLAMP_COLLECTION,
    )
    model["data"] = True
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.put("/v1/standard_clamp", response_model=ResponseBool)
async def update_standard_clamp(oneInfo: UpdateOneStandardClamp):
    """
    更新 标准夹具的tag的相关信息

    - :param oneInfo:
    - :return:
    """
    model = {}
    updateInfo = {
        "$set": {
            "version": oneInfo.version,
            "name": oneInfo.name,
            "desc": oneInfo.desc,
        }
    }
    update_mongo_value(
        filter_condition={"number": oneInfo.number},
        new_value=updateInfo,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_CLAMP_COLLECTION,
    )
    model["data"] = True
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.post("/v1/standard_clamp", response_model=ResponseStr)
async def upload_standard_clamp(file: UploadFile = File(...), desc: str = File(...), version: str = File(...)):
    """
    上传 标准夹具catia文件，并创建一条数据。
    TODO: 对未来，要考虑到如果有标准夹具的json中包含数据库里没有的零件的话，把这部分的标准夹具数据另外存一张数据库表，以便后来补上标准零件的信息。

    - :return:
    """
    isFeature: bool = False
    isFlag: bool = False
    folder = create_folder()
    file_path = f"{folder}/{file.filename}"
    # 写入文件
    write_file(file_path=file_path, file=file)
    model = {}
    # try:
    # 读取标准夹具的json文件
    standard_clamp = read_json(file_path)
    standard_part_name_list = [i for i in standard_clamp["elements"]]
    # 注意，这里的upload函数和其他几个不一样的是，它没有把数据丢到消息队列里，因为要先判断数据库里是否包含所有的标准零件。
    standardClampModel = upload_to_aliyun_standard_clamp_model(
        filename=file_path,
        jsonData=standard_clamp,
        desc=desc,
        version=version,
        isFeature=isFeature,
        isFlag=isFlag,
    )
    create_one_mongo_value(
        standardClampModel,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_CLAMP_COLLECTION,
    )
    model["data"] = standardClampModel["number"]
    model["status"] = 1
    # 这里多加一段判断夹具的json文件中的所有标准零件是否都已经在现有的数据库中了，只有是的话才会把数据放到消息队列中。
    if is_part_in_database(
            part_list=standard_part_name_list,
            database_name=MONGO_DATABASE_NAME,
            collection_name=STANDARD_PART_COLLECTION,
    ):
        if "_id" in standardClampModel.keys():
            standardClampModel.pop("_id")
        send_to_message_queue(standardClampModel, queue="upload2oss")
    return model


@deprecated_standard_clamp_router.get("/v1/standard_clamp_stl_file")
async def get_standard_clamp_stl_file(number: str):
    """
    显示模型接口，现阶段返回的是stl的数据。

    - :param number: 编号
    - :return:
    """
    model = {"data": ""}
    # retrieve_one_mongo_value返回的是一个只有一个元素的列表，取第一个
    original_data = retrieve_one_mongo_value(
        number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_CLAMP_COLLECTION,
    )
    if len(original_data) > 0:
        # 标准夹具现阶段是用stl文件来显示，后续考虑换成gltf
        model["data"] = original_data[0]["file"][STL_OSS_ADDRESS]
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.get("/v1/standard_clamp_json_file")
async def get_standard_clamp_json_file(number: str):
    """
    下载 模型数据（json格式的）
    - :param number: 编号
    - :return:
    """
    model = {"data": {}}
    # retrieve_one_mongo_value返回的是一个只有一个元素的列表，取第一个
    original_data = retrieve_one_mongo_value(
        number,
        database_name=MONGO_DATABASE_NAME,
        collection_name=STANDARD_CLAMP_COLLECTION,
    )
    if len(original_data) > 0:
        model["data"] = {
            "name": original_data[0]['name'],
            'path': original_data[0]['file'][JSON_OSS_ADDRESS],
        }
        model["status"] = 1
    else:
        model["status"] = 0

    return model


@deprecated_standard_clamp_router.get("/v1/standard_clamp")
async def retrieve_standard_clamp(number: str):
    """
    返回一条标准夹具的完整信息

    - :param number: 编号
    - :return:
    """
    model = {"data": {}}
    original_data = retrieve_one_mongo_value(number, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
    try:
        model["data"] = original_data[0]
        model["status"] = 1
    except:
        model["status"] = 0
    return model


@deprecated_standard_clamp_router.post("/v2/standard_clamp")
async def upload(request: Request, queryModel: UploadStandardClampModel):
    """

    - param jsonAliOssAddress: 用户上传的文件路径
    - param desc: 用户需要添加的描述
    - param version: 参数化模型的版本号
    - return:
    """
    number = standard_clamp_number_generator()
    standard_clamp = generate_standard_clamp_data(number, file_path=queryModel.jsonAliOssAddress, desc=queryModel.desc, version=queryModel.version)

    await request.app.state.redis.set(standard_clamp["number"], json.dumps(standard_clamp))

    create_one_mongo_value(standard_clamp, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
    send_to_message_queue(number)

    model = {"data": number, "status": 1}
    return model


@deprecated_standard_clamp_router.post("/v2/standard_clamps", response_model=ResponseDict)
async def multiple_condition_query_standard_clamps(request: Request, queryModel: MultipleConditionQueryStandardClamps):
    """
    ## 列表查询多条标准夹具。输入参数所有字段均可为空。


    - :param queryModel:
    - :return:
    """
    model = {"data": {"result": []}}

    # 先把redis中的符合历史夹具的key都拿出来
    standard_clamp_number_list = await request.app.state.redis.get("standard_clamp")
    standard_clamp_number_list = json.loads(standard_clamp_number_list)
    # 用上面的number列表去redis中查询所有历史夹具
    result = await request.app.state.redis.mget(*standard_clamp_number_list)
    result = [json.loads(i) for i in result]

    result = keyword_search_standard_clamp(queryModel, result)

    # result = filter_standard_clamp_under_20(result)
    model["data"]["total"] = len(result)
    model["data"]["result"] = separate_page(result, page=queryModel.page, pagesize=queryModel.pagesize)
    model["status"] = 1
    return model


@deprecated_standard_clamp_router.post("/v3/standard_clamp")
async def upload_v3(request: Request, queryModel: UploadStandardClampModel):
    """
    ## 上传标准夹具接口v3
    - param jsonAliOssAddress: 用户上传的文件路径
    - param desc: 用户需要添加的描述
    - param version: 参数化模型的版本号
    - return:
    """
    number = standard_clamp_number_generator()

    standard_clamp = generate_standard_clamp_data_v3(number, file_path=queryModel.jsonAliOssAddress, desc=queryModel.desc, version=queryModel.version)

    await request.app.state.redis.set(standard_clamp["number"], json.dumps(standard_clamp))

    create_one_mongo_value(standard_clamp, database_name=MONGO_DATABASE_NAME, collection_name=STANDARD_CLAMP_COLLECTION)
    send_to_message_queue(number)

    model = {"data": number, "status": 1}
    return model

